//=============================================================================
/**
 * @file	pair_reaction.c
 * @brief	連れ歩きリアクション処理
 * @author	saitou　GAME FREAK inc.
 *
 *　モジュール名：PairReact_
 */
//=============================================================================
#include "common.h"
#include "system/bmp_menu.h"
#include "field/weather_no.h"
#include "field/eventflag.h"
#include "battle/chr_def.h"
#include "battle/battle_common.h"
#include "poketool/poke_tool.h"
#include "fieldsys.h"
#include "ev_pokemon.h"
#include "itemtool/item.h"
#include "situation_local.h"
#include "ev_time.h"
#include "zonedata.h"
#include "check_data.h"
#include "eventdata.h"
#include "sxy.h"
#include "script.h"

#include "pair_reaction.h"

#include "msgdata/msg.naix"
#include "msgdata/msg_pair_reaction.h"
#include "msgdata/msg_common_scr.h"
#include "talk_msg.h"
#include "fieldmap.h"
#include "system/window.h"

#include "fldeff_pokeballon.h"

#include "system/snd_tool.h"
#include "system/snd_play.h"

#include "fld_bmp.h"

#include "savedata/imageclip_data.h"

#include "field_poketch.h"			//for FieldSubLcdControler_
#include "pair_poke.h"
#include "sysflag.h"

#define REACT_RECODE_MAX	(100)	//ゾーン依存30件+常駐70件
#define OCCUR_STATE_DATA_START	(600)

#define REACT_DATA_MAX	(5)
#define ACT_DATA_MAX	(10)

#define ACT_END	(0xff)
#define ACT_CODE_END	(0xffff)

#define PAIRMSG_TMP_SIZ	(1024)

#define VOICE_NORMAL	(SEQ_SE_END+1)

#define STATION_DATA_START	(30)			//常駐データ開始位置
#define PRI_MAX_STATION_DATA_NUM	(12)	//最優先常駐データ数

#define GET_LEAF	(0x0)
#define GET_ACCE	(0x2)
#define GET_ENABLE	(0x1)

#define LEAVES_MAX	(5)
#define LEAF00_MASK	(1)
#define LEAF01_MASK	(2)
#define LEAF02_MASK	(4)
#define LEAF03_MASK	(8)
#define LEAF04_MASK	(16)


#ifdef PM_DEBUG
#include "debug_saito.h"

///#define  DEBUG_ONLY	//自分のところだけデバッグプリント。無効で全員

#ifdef DEBUG_ONLY
#define DbgPrint	OS_Printf_saitou
#else
#define DbgPrint	OS_Printf
#endif	//DEBUG_ONLY

#else	//PM_DEBUG
#define DbgPrint	/* DO NOTHING */

#endif	//PM_DEBUG

typedef enum {
	SEQ_LOAD_ACTION,
	SEQ_SAVE_ORG_DIR_POS,
	SEQ_GET_DATA,
	SEQ_EXE_ACT,
	SEQ_SET_ORG_DIR_POS,
}SEQ;

//ジャンプアクションワーク
typedef struct
{
	u16 CountMax;
	u16 CountNow;
	TCB_PTR TcbAcmd;
}JUMP_ACT_WORK;

typedef struct REACT_OC_DATA_tag
{
	u8 HP;

	u8 Kigen:4;
	u8 Natsuki:4;

	u8 Person:3;
	u8 Sex:2;
	u8 State:3;

	u8 Item:5;
	u8 dmy:3;

	u8 Type:5;
	u8 Perform:3;

	u8 EncAttr;

	u8 Lineage;
	u8 Leaf;		//ここまでで8バイト

	u16 Weather:3;
	u16 SaveRC:10;
	u16 Dir:3;

	u16 Obj:3;
	u16 Time:3;
	u16 RC:10;

	u16 Zone;

	u16 Attr;

	u8 rest:1;
	u8 EncLv:2;
	u8 Skill:2;
	u8 HideItem:3;

	u8 Rnd;

	u16 Evt;

}REACT_OC_DATA;	//計20バイト

typedef struct REACT_BASE_DATA_tag{
	u16 ActCode;
	u16 Msg;
	u16 SE;
	u8 Ballon;
	u8 Wait;
}REACT_BASE_DATA;

typedef struct REACT_EXP_DATA_tag{
	int Select;
	u16 YesJump;
	u16 NoJump;
	s8 NatsukiVal;
	s8 KigenVal;
	u8 AcceNo;
	u8 LeafNo;
}REACT_EXP_DATA;

typedef struct REACT_DATA_tag{
	REACT_BASE_DATA Base[REACT_DATA_MAX];
	REACT_EXP_DATA Exp;
}REACT_DATA;

typedef struct ACT_DATA_tag{
	u8 Dir;
	u8 Frame;
	s8 Mx;
	s8 My;
	s8 Mz;
	u8 Snd;
	u8 dummy[2];
}ACT_DATA;

typedef struct REACTION_CONT_tag
{
	GF_BGL_BMPWIN Win;	// ウィンドウデータ
	STRBUF * Msg;		// メッセージ
	u8 PairReactData[2000];		//連れ歩きリアクションデータ
	REACT_DATA	ReactData;
	ACT_DATA	ActData[ACT_DATA_MAX];
	u8 Seq;
	u8 ReactSeq;
	u8 NowFrame;
	u8 ActCount;
	u8 ReactCount:4;
	u8 ReactMax:4;
	u8 Wait;
	u16	MsgIdx;			// メッセージインデックス

	VecFx32 OrgPos;
	u8 OrgDir;
	u8 Form;
	u16 MonsNo;

	u16 YesNoAns;
	u16 PokeAttr;
}REACTION_CONT;

typedef enum{
	MAX = 1,
	HIGHEST,
	HIGHER,
	HIGH,
	NORMAL,
	LOW,
	LOWER,
	LOWEST,
	OVER,
	UNDER,
}NATUKI_KIGEN;

typedef enum{
	S_NORMAL = 1,
	S_BURN,
	S_ICE,
	S_PARALYSIS,
	S_POISON,
	S_DEAD,		//連れ歩きが瀕死状態は無いけどコンバーターとの整合性のために
	S_ANY,
	S_SLEEP,	//コンバーターには無いけど入れておく
}STATE;

typedef enum{
	S_MALE = 1,
	S_FEMALE,
	S_NONE,
}SEX;

typedef enum{
	I_BALL = 1,
	I_DRUG,
	I_BATTLE,
	I_NORMAL,
	I_MAIL,
	I_NUTS,
	I_WAZA,
	I_NONE,
	I_ANY,
}ITEM_TYPE;

typedef enum{
	P_POWER = 1,
	P_QUICK,
	P_STAMINA,
	P_JUMP,
	P_TECHNIQUE,
}PERFORM;

typedef enum{
	T_NORMAL = 1,
	T_FIRE,
	T_WATER,
	T_ELECTR,
	T_GRASS,
	T_ICE,
	T_FIGHT,
	T_POISON,
	T_GROUND,
	T_FLYING,
	T_PSYCHC,
	T_BUG,
	T_ROCK,
	T_GHOST,
	T_DRAGON,
	T_DARK,
	T_STEEL,
}TYPE;

typedef enum{
	D_RIGHT = 1,
	D_LEFT,
	D_UP,
	D_DOWN,
}DIR;

typedef enum{
	P_FINE = 1,
	P_QUIET,
	P_CAUTIOUS,
	P_BRAVERY,
	P_LONELY,
	P_NATURE,
}PERSON;

typedef enum{
	W_SUNNY = 1,
	W_CLOUDINESS,
	W_RAIN,
	W_STRAIN,
	W_SPARK,
}WEATHER;

typedef enum{
	T_MORNING = 1,
	T_DAY,
	T_EVENING,
	T_NIGHT,
	T_MIDNIGHT,
}TIME;

typedef enum{
	S_STONE = 1,
	S_TREE,
	S_ROCK,
}SKILL;

typedef enum{
	O_ONE = 1,
	O_TWO,
	O_THREE,
	O_FOUR,
	O_MANY,
}OBJ;

typedef enum{
	H_ONE = 1,
	H_TWO,
	H_THREE,
	H_MANY,
}HITEM;

typedef enum{
	E_ON = 1,
	E_OFF,
}ENC;

typedef enum{
	H_MAX = 1,
	H_HIGH,
	H_MIDDLE,
	H_LOW,
	H_FEW,
}HP;

typedef enum{
	R_SEQ_GET_ACT_DATA,
	R_SEQ_GET_BALLON_DATA,
	R_SEQ_GET_MSG_DATA,
	R_SEQ_GET_WAIT,
	R_SEQ_NEXT,
	R_SEQ_EXE_ACTION,
	R_SEQ_EXE_MSG,
	R_SEQ_WAIT,
	R_SEQ_ITEM_GET,
	R_SEQ_LEAF_GET,
	R_SEQ_YES_NO_INIT,
	R_SEQ_YES_NO_MAIN_READY,
	R_SEQ_YES_NO_MAIN,
	R_SEQ_YES_NO_END,
}R_SEQ;

typedef enum{
	EXE_REACT_RC_LOOP,
	EXE_REACT_RC_END,
	EXE_REACT_RC_YESNO,
	EXE_REACT_RC_ACCE,
	EXE_REACT_RC_LEAF,
}EXE_REACT_RC;

//性格テーブル
static const PERSON PersonTbl[CHR_MAX+1] = {
	P_BRAVERY,		//CHR_GANBARIYA			がんばりや
	P_LONELY,		//CHR_SAMISIGARI		さみしがり
	P_BRAVERY,		//CHR_YUUKAN			ゆうかん
	P_BRAVERY,		//CHR_IZIPPARI			いじっぱり
	P_FINE,			//CHR_YANTYA			やんちゃ
	P_BRAVERY,		//CHR_ZUBUTOI			ずぶとい
	P_CAUTIOUS,		//CHR_SUNAO				すなお
	P_QUIET,		//CHR_NONKI				のんき
	P_FINE,			//CHR_WANPAKU			わんぱく
	P_QUIET,		//CHR_NOUTENKI			のうてんき
	P_LONELY,		//CHR_OKUBYOU			おくびょう
	P_NATURE,		//CHR_SEKKATI			せっかち
	P_CAUTIOUS,		//CHR_MAZIME			まじめ
	P_FINE,			//CHR_YOUKI				ようき
	P_FINE,			//CHR_MUZYAKI			むじゃき
	P_CAUTIOUS,		//CHR_HIKAEME			ひかえめ
	P_NATURE,		//CHR_OTTORI			おっとり
	P_CAUTIOUS,		//CHR_REISEI			れいせい
	P_LONELY,		//CHR_TEREYA			てれや
	P_NATURE,		//CHR_UKKARIYA			うっかりや
	P_QUIET,		//CHR_ODAYAKA			おだやか
	P_QUIET,		//CHR_OTONASII			おとなしい
	P_FINE,			//CHR_NAMAIKI			なまいき
	P_CAUTIOUS,		//CHR_SINTYOU			しんちょう
	P_NATURE,		//CHR_KIMAGURE			きまぐれ
};



typedef struct CHECK_DATA_tag
{
	u8 ItemHave;		//アイテム持ってるか
	u8 ItemType;
	u8 Hp;
	u8 State;

	u8 Lv;
	u8 Type1;
	u8 Type2;
	u8 Natsuki;

	u8 Person;
	u8 Sex;
	u8 Lineage;
	u8 Leaves;

	u8 ObjNum;
	u8 HideItemNum;
	u8 Iwakudaki;
	u8 Kairiki;

	u8 Iaigiri;
	u8 Weather;
	u8 Attr;
	u8 EncAttr;

	u8 TimeZone;
	s8 Kigen;
	u8 Perform;
	u8 Dir;

	u8 dummy[2];
	u16 Zone;
}CHECK_DATA;


//ポケモンパラムから取得できる情報を取得
static void GetPokeParam(POKEMON_PARAM *pp, CHECK_DATA *outData);
//自機の周囲にＯＢＪコードを持つ人物・物体の数を取得する
static void GetObjNum(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//隠しアイテムの数を取得する
static void GetHideItemNum(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//天候取得
static void GetWeather(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//連れ歩きのいる場所のアトリビュートを取得(エンカウントアトリビュートも取得する)
static void GetAttr(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//ゾーン取得
static void GetZone(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//現在時間を取得
static void GetTimeZone(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//機嫌値取得
static void GetKigenVal(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//連れ歩きの一番高いパフォーマンスを種得
static void GetPerform(FIELDSYS_WORK *fsys, const u16 inMonsNo, const u8 inForm, CHECK_DATA *outData);
//連れ歩きの向きを取得
static void GetPokeDir(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
//連れ歩き系統取得
static void GetPokeLineage(const int inMonsNo, CHECK_DATA *outData);

static u8 ConvPokeType(const int inType);
static u8 ConvItemType(const int inType);
static void MakeCheckData(FIELDSYS_WORK *fsys, CHECK_DATA *outData);
static BOOL CheckOccurData(	FIELDSYS_WORK *fsys,
							const REACT_OC_DATA *inData,
							const CHECK_DATA *inCheckData);

static EXE_REACT_RC ExecuteReaction(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr);

static BOOL GetActData(REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData);
static BOOL GetBallonData(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData);
static BOOL GetMsgData(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData);
static BOOL GetWait(REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData);
static void MsgSet(FIELDSYS_WORK * fsys, STRBUF * buf, const u32 inHeapID, const int inMsgID );
static void SetMsgTag(FIELDSYS_WORK * fsys, WORDSET * wset);
static void SetXYZ(const ACT_DATA *inData, FIELD_OBJ_PTR fldobj);
static void SetSE(const ACT_DATA *inData, const u16 inSE, const u16 inMonNo, const u8 inForm);
static void SetDir(REACTION_CONT_PTR ptr, const ACT_DATA *inData, FIELD_OBJ_PTR fldobj);
static void AddGrass(REACTION_CONT_PTR ptr, FIELD_OBJ_PTR fldobj, const u8 inOldDir);
static void GetBackPos(CONST_FIELD_OBJ_PTR fldobj, const u8 inDir, int *outX, int *outZ);
static BOOL ExeAction(REACTION_CONT_PTR ptr, FIELD_OBJ_PTR fldobj);
static BOOL GetData(REACTION_CONT_PTR ptr);
static BOOL Action(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const int inActCode);

static BOOL GMEVENT_PairReactionStart(GMEVENT_CONTROL * event);

static void SetReactAfterVal(FIELDSYS_WORK *fsys);
static BOOL CheckNatsuki(const u8 inNatsukiCode, const int inNatsukiVal);
static BOOL CheckKigen(const u8 inKigenCode, const int inKigenVal);
static BOOL CheckLineage(const u8 inLineage, const u8 inLineageVal);
static BOOL CheckLeaves(const u8 inLeaf, const u8 inLeaves);

static void SetItemGetMsg(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const u8 inMsgType);
static void MsgSet_GetItem(	FIELDSYS_WORK * fsys, STRBUF * buf, const u32 inHeapID,
							const u8 inMsgType, const u8 inAcceNo );

static BOOL GMEVENT_PairPokeJumpAct(GMEVENT_CONTROL * event);

#ifdef PM_DEBUG
static void DebugPrintArcData(const REACT_OC_DATA *inData);
static void DebugPrintfActData(const REACT_BASE_DATA *inData);
#endif

//--------------------------------------------------------------
///	ポケジャンプアニメ
//--------------------------------------------------------------
static const FIELD_OBJ_ACMD_LIST DATA_JumpAcmdTbl[4][5] =
{
	{
		{ AC_ANM_PAUSE_ON, 1 },
		{ AC_STAY_JUMP_U_8F, 1 },
		{ AC_WAIT_4F, 1 },
		{ AC_ANM_PAUSE_OFF, 1 },
		{ ACMD_END, 0 },
	},
	{
		{ AC_ANM_PAUSE_ON, 1 },
		{ AC_STAY_JUMP_D_8F, 1 },
		{ AC_WAIT_4F, 1 },
		{ AC_ANM_PAUSE_OFF, 1 },
		{ ACMD_END, 0 },
	},
	{
		{ AC_ANM_PAUSE_ON, 1 },
		{ AC_STAY_JUMP_L_8F, 1 },
		{ AC_WAIT_4F, 1 },
		{ AC_ANM_PAUSE_OFF, 1 },
		{ ACMD_END, 0 },
	},
	{
		{ AC_ANM_PAUSE_ON, 1 },
		{ AC_STAY_JUMP_R_8F, 1 },
		{ AC_WAIT_4F, 1 },
		{ AC_ANM_PAUSE_OFF, 1 },
		{ ACMD_END, 0 },
	},
};

//--------------------------------------------------------------
/**
 * イベントコール
 * @param	fsys		フィールドシステムポインタ
 *
 * @retval	none
 */
//--------------------------------------------------------------
void PairReact_CallEvnet(FIELDSYS_WORK * fsys)
{
	//イベントを作成
	FieldEvent_Call(fsys->event, GMEVENT_PairReactionStart, NULL);
}

//--------------------------------------------------------------
/**
 * 検索するリアクション発生条件データを読み込む
 * @param	fsys		フィールドシステムポインタ
 *
 * @retval	int			リアクションコード
 */
//--------------------------------------------------------------
int PairReact_GetReactCode(FIELDSYS_WORK *fsys)
{
	CHECK_DATA check_data;
	REACT_OC_DATA *data;
	int search[REACT_RECODE_MAX];
	int i;
	int place_id;
	place_id = ZoneData_GetPlaceNameID(fsys->location->zone_id);
	DbgPrint("PlaceID:%d\n",place_id);
	//現在の地名コード+1のリアクション発生条件データアーカイブをリードする
	ArchiveDataLoad(&fsys->ReactCntPtr->PairReactData[0], ARC_P_REACT_OCCUR, place_id+1);
	//常駐リアクション発生条件データアーカイブ(インデックス0)をリードする
	ArchiveDataLoad(&fsys->ReactCntPtr->PairReactData[OCCUR_STATE_DATA_START],
					ARC_P_REACT_OCCUR, 0);
	//条件判定に必要なデータを作成
	MakeCheckData(fsys, &check_data);

	OS_Printf("size=%d\n",sizeof(REACT_OC_DATA));
	data = (REACT_OC_DATA*)fsys->ReactCntPtr->PairReactData;

	//検索順番を作成
	{
		int count;
		count = 0;
		for(i=0;i<PRI_MAX_STATION_DATA_NUM;i++,count++){
			search[count] = STATION_DATA_START+i;
		}
		for(i=0;i<STATION_DATA_START;i++,count++){
			search[count] = i;
		}
		for(i=STATION_DATA_START+PRI_MAX_STATION_DATA_NUM;i<REACT_RECODE_MAX;i++,count++){
			search[count] = i;
		}
	}

	//検索開始
	for(i=0;i<REACT_RECODE_MAX;i++){
		int idx;
		BOOL rc;
		idx = search[i];
#ifdef PM_DEBUG
		DebugPrintArcData(&data[idx]);
#endif
		if (!data[idx].RC){
			DbgPrint("%d番目はリアクションコード無し\n",i);
			continue;
		}
		DbgPrint("%d番目を検証\n",idx);
		rc = CheckOccurData( fsys, &data[idx], &check_data);
		if (rc){
			OS_Printf("採用リアクションコード%d\n",data[idx].RC);
			return data[idx].RC;
		}
	}
	//1件も引っかからなかった
	DbgPrint("リアクションコード取得失敗\n");
	GF_ASSERT(0);
	return 0;
}

//--------------------------------------------------------------
/**
 * チェックに必要なデータをあらかじめ作成する
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void MakeCheckData(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	POKEMON_PARAM *pp;
	//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
	pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));

	//モンスターナンバーとフォルムを取得
	fsys->ReactCntPtr->MonsNo = PokeParaGet(pp,ID_PARA_monsno,NULL);
	fsys->ReactCntPtr->Form = PokeParaGet(pp,ID_PARA_form_no,NULL);

	GetPokeParam(pp, outData);
	GetObjNum(fsys, outData);
	GetHideItemNum(fsys, outData);
	GetWeather(fsys, outData);
	GetAttr(fsys, outData);
	GetZone(fsys, outData);
	GetTimeZone(fsys, outData);
	GetKigenVal(fsys, outData);
	GetPerform(fsys, fsys->ReactCntPtr->MonsNo, fsys->ReactCntPtr->Form, outData);
	GetPokeDir(fsys, outData);
	GetPokeLineage(fsys->ReactCntPtr->MonsNo, outData);

}

//--------------------------------------------------------------
/**
 * 読み込んだ発生条件データを1つずつ検証する
 * @param	fsys		フィールドシステムポインタ
 * @param	inData		リアクション発生データポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	BOOL		TRUEで発生
 */
//--------------------------------------------------------------
static BOOL CheckOccurData(	FIELDSYS_WORK *fsys,
							const REACT_OC_DATA *inData,
							const CHECK_DATA *inCheckData)
{
	//乱数
	if ( !(gf_rand()%100 < inData->Rnd) ){
		DbgPrint("乱数ではじかれた\n");
		return FALSE;
	}

	//イベントフラグ
	if ( inData->Evt != 0 ){		//フラグ成立をチェックする
		BOOL rc;
		rc = EventWork_CheckEventFlag( SaveData_GetEventWork(fsys->savedata), inData->Evt);
		if (!rc){
			return FALSE;
		}
	}

	//記憶
	if ( (inData->SaveRC != 0)&&(0) ){
		return FALSE;
	}

	//所持アイテム
	if ( inData->Item != 0 ){
		if (inData->Item == I_ANY){
			if (!inCheckData->ItemHave){
				return FALSE;
			}
		}else{
			if (inData->Item != inCheckData->ItemType){
				return FALSE;
			}
		}
	}

	//残りＨＰ
	if ( inData->HP != 0 ){//残りＨＰ割合をチェック
		if (inData->HP != inCheckData->Hp){
			return FALSE;
		}
	}

	//状態
	if ( inData->State != 0 ){	//状態チェック
		if (inData->State == S_ANY){
			//いずれかの状態異常か？
			if ( (inCheckData->State != S_BURN)&&
				 (inCheckData->State != S_ICE)&&
				 (inCheckData->State != S_PARALYSIS)&&
				 (inCheckData->State != S_POISON)&&
				 (inCheckData->State != S_SLEEP)) {
				return FALSE;
			}
		}else if (inData->State!=inCheckData->State){
			return FALSE;
		}
	}

	//周囲ＯＢＪ
	if ( inData->Obj != 0 ){
		if (inData->Obj == O_MANY){
			if (inCheckData->ObjNum < O_MANY ){
				return FALSE;
			}
		}else{
			if ( inData->Obj != inCheckData->ObjNum ){
				return FALSE;
			}
		}
	}

	//隠しアイテム
	if ( inData->HideItem != 0 ){
		if (inData->HideItem == H_MANY){
			if (inCheckData->HideItemNum < H_MANY ){
				return FALSE;
			}
		}else{
			if ( inData->HideItem != inCheckData->HideItemNum ){
				return FALSE;
			}
		}
	}

	//エンカウントレベル
	if ( inData->EncLv != 0){
		if ( inData->EncLv != inCheckData->Lv ){
			return FALSE;
		}
	}
	//秘伝
	if ( inData->Skill != 0 ){
		if ( (inData->Skill == S_ROCK)&&(!inCheckData->Iwakudaki) ){
			return FALSE;
		}else if( (inData->Skill == S_STONE)&&(!inCheckData->Kairiki) ){
			return FALSE;
		}else if( (inData->Skill == S_TREE)&&(!inCheckData->Iaigiri) ){
			return FALSE;
		}
		return FALSE;
	}
	//タイプ
	if ( inData->Type != 0 ){
		if ( (inData->Type!=inCheckData->Type1)&&(inData->Type!=inCheckData->Type2) ){
			return FALSE;
		}
	}
	//天気
	if ( inData->Weather != 0 ){
		if (inData->Weather != inCheckData->Weather){
			return FALSE;
		}
	}
	//アトリビュート
	if ( inData->Attr != 0 ){
		if (inData->Attr!=inCheckData->Attr){
			return FALSE;
		}
	}

	//エンカウント
	if ( inData->EncAttr != 0 ){
		if (inData->EncAttr!=inCheckData->EncAttr){
			return FALSE;
		}
	}

	//ゾーン
	if ( inData->Zone != 0 ){
		if (inData->Zone-1 != inCheckData->Zone){
			return FALSE;
		}
	}

	//時刻
	if ( inData->Time != 0 ){
		if (inData->Time != inCheckData->TimeZone){
			return FALSE;
		}
	}

	//機嫌値
	if ( inData->Kigen != 0 ){
		if ( !CheckKigen(inData->Kigen, inCheckData->Kigen) ){
			return FALSE;
		}
	}

	//パフォーマンス
	if ( inData->Perform != 0 ){
		if (inData->Perform != inCheckData->Perform){
			return FALSE;
		}
	}
	//なつき度
	if ( inData->Natsuki != 0 ){
		if ( !CheckNatsuki(inData->Natsuki, inCheckData->Natsuki) ){
			return FALSE;
		}
	}

	//性格
	if ( inData->Person != 0 ){
		if (inData->Person != inCheckData->Person){
			return FALSE;
		}
	}

	//系統
	if ( inData->Lineage != 0 ){
		if ( !CheckLineage(inData->Lineage, inCheckData->Lineage) ){
			return FALSE;
		}
	}

	//葉っぱ（取得していたら条件を満たさない）
	if ( inData->Leaf != 0 ){
		if ( !CheckLeaves(inData->Leaf, inCheckData->Leaves) ){
			return FALSE;
		}
	}

	//オスメス
	if ( inData->Sex != 0 ){
		if (inData->Sex != inCheckData->Sex){
			return FALSE;
		}
	}

	//向き
	if ( inData->Dir != 0 ){
		if (inData->Dir != inCheckData->Dir){
			return FALSE;
		}
	}

	return TRUE;
}

//------------------------------------------------------------------------------------------------

//--------------------------------------------------------------
/**
 * ポケモンパラムから取得できる情報を取得
 * @param	pp			ポケモンパラメータポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetPokeParam(POKEMON_PARAM *pp, CHECK_DATA *outData)
{
	int heap_id = HEAPID_WORLD;
	//所持アイテムタイプ
	{
		int item = PokeParaGet(pp,ID_PARA_item,NULL);
		if (item){
			outData->ItemHave = 1;
			outData->ItemType = ConvItemType( ItemParamGet( item, ITEM_PRM_POCKET, heap_id ) );
			DbgPrint("所持アイテム:%d ポケットタイプ:%d\n",item, outData->ItemType);
		}else{
			outData->ItemHave = 0;
			outData->ItemType = I_NONE;
			DbgPrint("所持アイテムなし\n");
		}
	}
	//残りＨＰパーセント
	{
		int hp,hp_max, per;
		hp = PokeParaGet(pp,ID_PARA_hp,NULL);
		hp_max = PokeParaGet(pp,ID_PARA_hpmax,NULL);
		per = (hp*100)/hp_max;
		if (per == 100){
			outData->Hp = H_MAX;
		}else if(per >= 75){
			outData->Hp = H_HIGH;
		}else if(per >= 50 ){
			outData->Hp = H_MIDDLE;
		}else if(per >= 25){
			outData->Hp = H_LOW;
		}else{
			outData->Hp = H_FEW;
		}
		DbgPrint("ＨＰ:%d/%d >> code:%d\n",hp, hp_max, outData->Hp);
	}
	//状態
	{
		int cond = PokeParaGet(pp,ID_PARA_condition,NULL);
		if ( (cond & (CONDITION_DOKU|CONDITION_DOKUDOKU)) != 0){	//毒
			outData->State = S_POISON;
		}else if( (cond & CONDITION_NEMURI) != 0 ){					//眠り
			outData->State = S_SLEEP;
		}else if( (cond & CONDITION_YAKEDO) != 0 ){					//やけど
			outData->State = S_BURN;
		}else if( (cond & CONDITION_KOORI) != 0 ){					//こおり
			outData->State = S_ICE;
		}else if( (cond & CONDITION_MAHI) != 0 ){					//まひ
			outData->State = S_PARALYSIS;
		}else if( cond == CONDITION_NOCHECK ){						//状態異常なし
			outData->State = S_NORMAL;
		}else {
			GF_ASSERT(0);
			outData->State = S_NORMAL;
		}

		DbgPrint("ポケモンの状態:%d　>> code:%d\n",cond, outData->State);
	}
	//レベル
	{
		int lv_max;
		int lv = PokeParaGet(pp,ID_PARA_level,NULL);
		//ここでエンカウントするポケモンの最高レベルを取得
		lv_max = 50;
		if (lv+2 >= lv_max){
			outData->Lv = HIGH;
		}else if(lv-2 <= lv_max){
			outData->Lv = LOW;
		}else{
			outData->Lv = NORMAL;
		}
		DbgPrint("ポケLv:%d 出現最大Lv%d >> code:%d\n",lv, lv_max, outData->Lv);
	}
	//タイプ
	{
		int type1 = PokeParaGet(pp,ID_PARA_type1,NULL);
		int type2 = PokeParaGet(pp,ID_PARA_type2,NULL);
		outData->Type1 = ConvPokeType(type1);
		outData->Type2 = ConvPokeType(type2);
		DbgPrint("タイプ:%d_%d >> code:%d_%d\n",type1, type2, outData->Type1, outData->Type2);
	}
	//なつき度
	{
		int natsuki = PokeParaGet(pp,ID_PARA_friend,NULL);
		outData->Natsuki = natsuki;
		DbgPrint("なつき度:%d\n",natsuki);
	}
	//性格
	{
		int person = PokeSeikakuGet(pp);
		outData->Person = PersonTbl[person];
		DbgPrint("性格:%d >> code:%d\n",person, outData->Person);
	}
	//性別
	{
		int sex = PokeParaGet(pp,ID_PARA_sex,NULL);
		if (sex == PARA_MALE){
			outData->Sex = S_MALE;
		}else if(sex = PARA_FEMALE){
			outData->Sex = S_FEMALE;
		}else{
			outData->Sex = S_NONE;
		}
		DbgPrint("性別:%d >> code:%d\n",sex, outData->Sex);
	}
	//葉っぱ
	{
		int i;
		int leaves[LEAVES_MAX] = {
			ID_PARA_leaf0,
			ID_PARA_leaf1,
			ID_PARA_leaf2,
			ID_PARA_leaf3,
			ID_PARA_leaf4
		};
		outData->Leaves = 0;
		for (i=0; i<LEAVES_MAX; i++){
			u8 bit;
			bit = PokeParaGet(pp, leaves[i], NULL);
			outData->Leaves |= (bit << i);
		}
	}
}

//--------------------------------------------------------------
/**
 * 自機の周囲にＯＢＪコードを持つ人物・物体の数を取得する
 * 画面にある壊せる岩・切れる木・押せる岩の有無をチェックする
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetObjNum(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	int i;
	int max;
	FIELD_OBJ_PTR fldobj;
	int px,pz;

	outData->ObjNum = 0;
	outData->Iwakudaki = 0;
	outData->Kairiki = 0;
	outData->Iaigiri = 0;

	px = Player_NowGPosXGet( fsys->player );
	pz = Player_NowGPosZGet( fsys->player );

	max = FieldOBJSys_OBJMaxGet( fsys->fldobjsys );
	fldobj = FieldOBJSys_FldOBJWorkGet( fsys->fldobjsys );
	for(i=0;i<max;i++){
		if( FieldOBJ_StatusBitCheck_Use(fldobj) == TRUE ){
			int x_dif,z_dif,x,z;
			int code;
			//座標取得
			x = FieldOBJ_NowPosGX_Get(fldobj);
			z = FieldOBJ_NowPosGZ_Get(fldobj);
			x_dif = px - x;
			z_dif = pz - z;
			code = FieldOBJ_OBJCodeGet( fldobj );
			if (code == ROCK){
				outData->Kairiki = 1;
			}else if(code == BREAKROCK){
				outData->Iwakudaki = 1;
			}else if(code == TREE){
				outData->Iaigiri = 1;
			}else{
				//自機周りの座標か？
				if ( (-1<=x_dif)&&(x_dif<=1)&&(-1<=z_dif)&&(z_dif<=1) ){
					int obj_id = FieldOBJ_OBJIDGet( fldobj );
					//自分・連れ歩きではない
					if ( (obj_id != FLDOBJ_ID_POKE_PAIR)&&(obj_id != FLDOBJ_ID_PLAYER) ){
						outData->ObjNum++;
					}
				}
			}
		}
		FieldOBJSys_FldOBJWorkInc( &fldobj );
	}
	DbgPrint("OBJ数:%d\n",outData->ObjNum);
	DbgPrint("怪力;%d 岩砕き;%d いあいぎり:%d\n",outData->Kairiki,outData->Iwakudaki,outData->Iaigiri);
}

//--------------------------------------------------------------
/**
 * 隠しアイテムの数を取得する
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetHideItemNum(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	int i;
	const BG_TALK_DATA* bg;
	int num;
	int max;

	num = 0;
	//BGデータ取得
	bg	= EventData_GetNowBgTalkData( fsys );
	//BGデータ数取得
	max = EventData_GetNowBgTalkDataSize( fsys );
	//BGデータが存在していなかった時
	if( !max){
		num = 0;
	}else if( bg == NULL ){
		num = 0;
	}else{
		//BGデータ分サーチをかける
		for( i=0; i < max ;i++ ){
			//隠しアイテムタイプで、まだ入手していなかったら
			if( (bg[i].type == BG_TALK_TYPE_HIDE) &&
				(CheckEventFlag(fsys, GetHideItemFlagNoByScriptId(bg[i].id)) == 0) ){
				num++;
			}
		}
	}
	outData->HideItemNum = num;
	DbgPrint("隠しアイテム数:%d\n",outData->HideItemNum);
}

//--------------------------------------------------------------
/**
 * 天候取得
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetWeather(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	int weather;
	weather = Situation_GetWeatherID(	SaveData_GetSituation(fsys->savedata) );
	switch(weather){
	case WEATHER_SYS_SUNNY:			// 晴れ
		outData->Weather = W_SUNNY;
		break;
/**
	case WEATHER_SYS_CLOUDINESS:	// 曇り		BG
		outData->Weather = W_CLOUDINESS;
		break;*/
	case WEATHER_SYS_RAIN:			// 雨		OAM	FOG
		outData->Weather = W_RAIN;
		break;
/**
	case WEATHER_SYS_STRAIN:		// 大雨		OAM FOG
		outData->Weather = W_STRAIN;
		break;
	case WEATHER_SYS_SPARK:			// 大雨		OAM FOG BG
		outData->Weather = W_SPARK;
		break;*/
	default:
		outData->Weather = 0;
	}
	DbgPrint("天気コード%d >> code:%d\n",weather, outData->Weather);
}

//--------------------------------------------------------------
/**
 * 連れ歩きのいる場所のアトリビュートを取得(エンカウントアトリビュートも取得する)
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetAttr(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	u8 attr;
	int x,z;
	x = FieldOBJ_NowPosGX_Get( PairPoke_GetFldObjPtr(fsys) );
	z = FieldOBJ_NowPosGZ_Get( PairPoke_GetFldObjPtr(fsys) );
	attr = (u8)GetAttributeLSB( fsys, x, z );

	outData->Attr = attr;
	fsys->ReactCntPtr->PokeAttr = attr;

	if ( MATR_IsEncount(attr) ){
		outData->EncAttr = E_ON;
	}else{
		outData->EncAttr = E_OFF;
	}
	DbgPrint("エンカウント:%d アトリビュート:%d\n",outData->EncAttr, outData->Attr);
}

//--------------------------------------------------------------
/**
 * ゾーン取得
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetZone(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	outData->Zone = fsys->location->zone_id;
}

//--------------------------------------------------------------
/**
 * 時間帯取得
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetTimeZone(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	int time_zone;
	time_zone = EVTIME_GetTimeZone(fsys);
	switch(time_zone){
	case TIMEZONE_MORNING:
		outData->TimeZone = T_MORNING;
		break;
	case TIMEZONE_NOON:
		outData->TimeZone = T_DAY;
		break;
	case TIMEZONE_EVENING:
		outData->TimeZone = T_EVENING;
		break;
	case TIMEZONE_NIGHT:
		outData->TimeZone = T_NIGHT;
		break;
	case TIMEZONE_MIDNIGHT:
		outData->TimeZone = T_MIDNIGHT;
		break;
	default:
		GF_ASSERT(0);
		outData->TimeZone = 0;
	}
	DbgPrint("時間帯%d\n",outData->TimeZone);
}

//--------------------------------------------------------------
/**
 * 機嫌値取得
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetKigenVal(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	outData->Kigen = PAIR_POKE_HUMOR_GetVal(fsys->PairPokeHumor);

	DbgPrint("機嫌値:%d\n", outData->Kigen);
}

//--------------------------------------------------------------
/**
 * 連れ歩きの一番高いパフォーマンスを種得
 *
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	inMonsNo	モンスターナンバー
 * @param	inForm		フォルム
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetPerform(FIELDSYS_WORK *fsys, const u16 inMonsNo, const u8 inForm, CHECK_DATA *outData)
{
	PERFORM per;
	POKEPARTY *ppt;
	PM_CONDITION pc;
	u8 pos;
	PM_PERFORMANCE pp;
	u16 param;

	ppt = SaveData_GetTemotiPokemon(fsys->savedata);

	pos = EvPoke_GetLivingPokeIdxTop(ppt);

	PokeParty_GetPokeCondition(ppt, &pc, pos);
	GetPokePerformance(&pp,PokeParty_GetMemberPointer(ppt,pos), &pc, HEAPID_WORLD);

	param = pp.power;
	per = P_POWER;
	if (param < pp.speed){
		param = pp.speed;
		per = P_QUICK;
	}
	if (param < pp.jump){
		param = pp.jump;
		per = P_JUMP;
	}
	if (param < pp.stamina){
		param = pp.stamina;
		per = P_STAMINA;
	}
	if (param < pp.technique){
		param = pp.technique;
		per = P_TECHNIQUE;
	}
	outData->Perform = per;
}

//--------------------------------------------------------------
/**
 * 連れ歩きの向きを取得
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------

static void GetPokeDir(FIELDSYS_WORK *fsys, CHECK_DATA *outData)
{
	int dir;
	dir = FieldOBJ_DirDispGet(fsys->PairPokeWork.FldObj);
	switch(dir){
	case DIR_UP:
		outData->Dir = D_UP;
		break;
	case DIR_DOWN:
		outData->Dir = D_DOWN;
		break;
	case DIR_LEFT:
		outData->Dir = D_LEFT;
		break;
	case DIR_RIGHT:
		outData->Dir = D_RIGHT;
		break;
	default:
		outData->Dir = 0;
	}
	DbgPrint("方向:%d >> code:%d\n",dir, outData->Dir);
}

//--------------------------------------------------------------
/**
 * 連れ歩き系統取得
 *
 *
 * @param	inMonsNo	モンスターナンバー
 * @param	outData		作成データ格納バッファ
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetPokeLineage(const int inMonsNo, CHECK_DATA *outData)
{
	u8 *figure_tbl;
	if ( (inMonsNo <= 0)||( MONSNO_END < inMonsNo) ){
		GF_ASSERT(0);
		return;
	}
	//アーカイブから、系統テーブルをロード
	figure_tbl = ArchiveDataLoadMallocLo(ARC_P_FIGURE, 0, HEAPID_WORLD);

	outData->Lineage = figure_tbl[inMonsNo-1];

	sys_FreeMemoryEz(figure_tbl);
}

//--------------------------------------------------------------------------------------------------

//--------------------------------------------------------------
/**
 * バトルで使用するポケモンタイプを連れ歩きバイナリデータのタイプに変換
 *
 *
 * @param	inType		タイプ
 *
 * @retval	u8			変換後タイプ
 */
//--------------------------------------------------------------
static u8 ConvPokeType(const int inType)
{
	u8 rc;
	switch(inType){
	case NORMAL_TYPE:
		rc = T_NORMAL;
		break;
	case BATTLE_TYPE:
		rc = T_FIGHT;
		break;
	case HIKOU_TYPE:
		rc = T_FLYING;
		break;
	case POISON_TYPE:
		rc = T_POISON;
		break;
	case JIMEN_TYPE:
		rc = T_GROUND;
		break;
	case IWA_TYPE:
		rc = T_ROCK;
		break;
	case MUSHI_TYPE:
		rc = T_BUG;
		break;
	case GHOST_TYPE:
		rc = T_GHOST;
		break;
	case METAL_TYPE:
		rc = T_STEEL;
		break;
	case FIRE_TYPE:
		rc = T_FIRE;
		break;
	case WATER_TYPE:
		rc = T_WATER;
		break;
	case KUSA_TYPE:
		rc = T_GRASS;
		break;
	case ELECTRIC_TYPE:
		rc = T_ELECTR;
		break;
	case SP_TYPE:
		rc = T_PSYCHC;
		break;
	case KOORI_TYPE:
		rc = T_ICE;
		break;
	case DRAGON_TYPE:
		rc = T_DRAGON;
		break;
	case AKU_TYPE:
		rc = T_DARK;
		break;
	default:
		GF_ASSERT(0);
		rc = 0;
	}
	return rc;
}

//--------------------------------------------------------------
/**
 * アイテムのポケットタイプを連れ歩きバイナリデータタイプに変換
 *
 *
 * @param	inType		タイプ
 *
 * @retval	u8			変換後タイプ
 */
//--------------------------------------------------------------
static u8 ConvItemType(const int inType)
{
	u8 rc;
	switch(inType){
	case BAG_POKE_NORMAL:	// 道具
		rc = I_NORMAL;
		break;
	case BAG_POKE_DRUG:		// 薬
		rc = I_DRUG;
		break;
	case BAG_POKE_BALL:		// ボール
		rc = I_BALL;
		break;
	case BAG_POKE_WAZA:		// 技マシン
		rc = I_WAZA;
		break;
	case BAG_POKE_NUTS:		// 木の実
		rc = I_NUTS;
		break;
	case BAG_POKE_SEAL:		// メール
		rc = I_MAIL;
		break;
	case BAG_POKE_BATTLE:	// 戦闘用
		rc = I_BATTLE;
		break;
	default:
		GF_ASSERT(0);
		rc = I_NONE;
	}
	return rc;
}

//------------------------------------------------------------------
/**
 * @brief	リアクションコントローラアロケーション
 *
 * @param	inHeapID	ヒープID
 *
 * @return	ptr		リアクション管理ポインタ
 */
//------------------------------------------------------------------
REACTION_CONT_PTR PairReact_Alloc(const int inHeapID)
{
	REACTION_CONT_PTR ptr;
	int size;
	size = sizeof(REACTION_CONT);
	ptr = sys_AllocMemory( inHeapID, size );

	MI_CpuClear8(ptr, size);

	return ptr;
}

//------------------------------------------------------------------
/**
 * @brief	リアクションコントローラセットアップ
 *
 * @param	ptr				リアクション管理ポインタ
 * @param	inReactCode		リアクションコード
 *
 * @return	none
 */
//------------------------------------------------------------------
void PairReact_Setup(REACTION_CONT_PTR ptr, const int inReactCode)
{
	const REACT_BASE_DATA * data;
	int i;
	DbgPrint("リアクションアーカイブインデックス:%d\n",inReactCode-1);
	ArchiveDataLoad(&ptr->ReactData, ARC_P_REACT, inReactCode-1);
	ptr->Seq = 0;
	ptr->ReactSeq = R_SEQ_GET_ACT_DATA;
	ptr->ActCount = 0;
	ptr->ReactCount = 0;
	ptr->NowFrame = 0;
	ptr->Wait = 0;
	ptr->MsgIdx = 0;
	//リアクション数を取得
	for(i=0;i<REACT_DATA_MAX;i++){
		data = &ptr->ReactData.Base[i];
		if ( data->ActCode == ACT_CODE_END ){
			break;
		}
	}
	ptr->ReactMax = i;
}

//------------------------------------------------------------------
/**
 * @brief	リアクションコントローラセット解放
 *
 * @param	ptr				リアクション管理ポインタ
 *
 * @return	none
 */
//------------------------------------------------------------------
void PairReact_Free(REACTION_CONT_PTR ptr)
{
	sys_FreeMemoryEz(ptr);
}

//------------------------------------------------------------------
/**
 * @brief	リアクションデータを解釈する
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	ptr				リアクション管理ポインタ
 *
 * @return	EXE_REACT_RC		リアクション結果コードenum参照
 */
//------------------------------------------------------------------
static EXE_REACT_RC ExecuteReaction(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr)
{
	BOOL rc;
	const REACT_BASE_DATA * data;

	//カウント数チェック
	if (ptr->ReactCount>=REACT_DATA_MAX){
		DbgPrint("リアクション5個フル使用で終了\n");
		//なつき度と機嫌値の変更
		SetReactAfterVal(fsys);
		//分岐があるかをチェック
		if ( ptr->ReactData.Exp.Select ){
			return EXE_REACT_RC_YESNO;	//分岐
		}else if (ptr->ReactData.Exp.AcceNo){
			return EXE_REACT_RC_ACCE;
		}else if (ptr->ReactData.Exp.LeafNo){
			return EXE_REACT_RC_LEAF;
		}else{
			return EXE_REACT_RC_END;	//終了
		}
	}
	//次データ取得
	data = &ptr->ReactData.Base[ ptr->ReactCount ];
#ifdef PM_DEBUG
	DebugPrintfActData(data);
#endif

	//データ終了チェック
	if (data->ActCode == ACT_CODE_END){
		DbgPrint("リアクション%d個目はないので終了\n",ptr->ReactCount+1);
		//なつき度と機嫌値の変更
		SetReactAfterVal(fsys);
		//分岐があるかをチェック
		if ( ptr->ReactData.Exp.Select ){
			return EXE_REACT_RC_YESNO;	//分岐選択
		}else if (ptr->ReactData.Exp.AcceNo){
			return EXE_REACT_RC_ACCE;
		}else if (ptr->ReactData.Exp.LeafNo){
			return EXE_REACT_RC_LEAF;
		}else{
			return EXE_REACT_RC_END;	//終了
		}
	}

	DbgPrint("リアクション%d個目\n",ptr->ReactCount+1);

	switch (ptr->ReactSeq){
	case R_SEQ_GET_ACT_DATA:
		//アクションデータを取得
		rc = GetActData(ptr, data);
		if (rc){
			//連れ歩きのポーズ状態を解除
			FieldOBJ_MovePauseClear( fsys->PairPokeWork.FldObj );
			ptr->Seq = SEQ_LOAD_ACTION;
			//シーケンスをアクション終了待ちシーケンスに変更
			ptr->ReactSeq = R_SEQ_EXE_ACTION;
			break;
		}
	case R_SEQ_GET_BALLON_DATA:
		//吹き出しデータ取得
		rc = GetBallonData(fsys, ptr, data);
		if (rc){
			//連れ歩きのポーズ状態を解除
			FieldOBJ_MovePauseClear( fsys->PairPokeWork.FldObj );
			//シーケンスをメッセージ取得シーケンスに変更。
			//吹き出しはイベントコールなので、シーケンス変更してもイベント終了まで、次のシーケンスはフックされる
			ptr->ReactSeq = R_SEQ_GET_MSG_DATA;
			break;
		}
	case R_SEQ_GET_MSG_DATA:
		//メッセージデータ取得
		rc = GetMsgData(fsys, ptr, data);
		if (rc){
			//連れ歩きをポーズ状態にする
			FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
			//シーケンスをメッセージ終了待ちシーケンスに変更
			ptr->ReactSeq = R_SEQ_EXE_MSG;
			break;
		}
	case R_SEQ_GET_WAIT:
		//ウェイト取得
		rc = GetWait(ptr, data);
		if (rc){
			//シーケンスをウェイト待ちシーケンスに変更
			ptr->ReactSeq = R_SEQ_WAIT;
			break;
		}
	case R_SEQ_NEXT:
		//次のリアクションデータに変更
		ptr->ReactCount++;
		ptr->ReactSeq = R_SEQ_GET_ACT_DATA;
		break;

	case R_SEQ_EXE_ACTION:
		rc = Action(fsys, ptr, data->ActCode);
		if (rc){
			//シーケンスを吹き出し取得シーケンスへ
			ptr->ReactSeq = R_SEQ_GET_BALLON_DATA;
		}
		break;
	case R_SEQ_EXE_MSG:
		if( FldTalkMsgEndCheck( ptr->MsgIdx ) == 1 ){
			//最終メッセージか？
			if ( ptr->ReactMax > ptr->ReactCount+1){
				//NO
				//キー入力でウィンドウ消す
				if(sys.trg & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
					BmpTalkWinClear( &ptr->Win, WINDOW_TRANS_ON );
					GF_BGL_BmpWinDel( &ptr->Win );
					STRBUF_Delete( ptr->Msg );
					fsys->sublcd_menu_next_flag = 0;		//会話中フラグ落とす
					//シーケンスをウェイト取得シーケンスへ
					ptr->ReactSeq = R_SEQ_GET_WAIT;
				}
			}else{
				//YES
				//分岐あり？
				if ( ptr->ReactData.Exp.Select ){	//あり
					//キー不要
					//シーケンスをウェイト取得シーケンスへ
					ptr->ReactSeq = R_SEQ_GET_WAIT;
				}else{								//なし
					//キー入力でウィンドウ消す
					if(sys.trg & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
						BmpTalkWinClear( &ptr->Win, WINDOW_TRANS_ON );
						GF_BGL_BmpWinDel( &ptr->Win );
						STRBUF_Delete( ptr->Msg );
						fsys->sublcd_menu_next_flag = 0;		//会話中フラグ落とす
						//シーケンスをウェイト取得シーケンスへ
						ptr->ReactSeq = R_SEQ_GET_WAIT;
					}
				}
			}
		}
		break;
	case R_SEQ_WAIT:
		//ウェイト
		if (ptr->Wait >= data->Wait){
			//アクションデータ数カウントアップ
			ptr->ReactCount++;
			ptr->ReactSeq = R_SEQ_GET_ACT_DATA;
		}else{
			ptr->Wait++;
			DbgPrint("NowWait\n");
		}
		break;
	}

	return EXE_REACT_RC_LOOP;
}

//------------------------------------------------------------------
/**
 * @brief	アクションデータ取得
 *
 * @param	ptr				リアクション管理ポインタ
 * @param	inData			リアクション基本データ
 *
 * @return	BOOL		TRUE:データある	FALSE:データない
 */
//------------------------------------------------------------------
static BOOL GetActData(REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData)
{
	if (inData->ActCode){
		//アクションデータロード
		DbgPrint("アクションコードあり:%d\n",inData->ActCode);
		return TRUE;
	}else{
		//アクションしない
		return FALSE;
	}
}

//------------------------------------------------------------------
/**
 * @brief	吹き出しデータ取得
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	ptr				リアクション管理ポインタ
 * @param	inData			リアクション基本データ
 *
 * @return	BOOL			TRUE:吹き出しある	FALSE:吹き出しない
 */
//------------------------------------------------------------------
static BOOL GetBallonData(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData)
{

	//連れ歩きが橋のアトリビュート、吹き出し禁止アトリビュートを踏んでいる場合は吹き出しを出さない
	if ( MATR_IsInvisibleBallon( fsys->ReactCntPtr->PokeAttr ) ){
		OS_Printf("吹き出し出さないアトリビュートを踏んだので吹き出しださない\n");
		return FALSE;
	}

	if (inData->Ballon){
		//吹き出し用意
		if (inData->Ballon > BALLON_MAX){
			DbgPrint("吹き出しインデックスオーバー:%d\n",inData->Ballon);
			return FALSE;
		}
		DbgPrint("吹き出しあり:%d\n",inData->Ballon);
		PokeBallon_CallEvent(fsys, fsys->PairPokeWork.FldObj, inData->Ballon-1);
		return TRUE;
	}else{
		//吹き出しなし
		return FALSE;
	}
}

//------------------------------------------------------------------
/**
 * @brief	メッセージデータ取得
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	ptr				リアクション管理ポインタ
 * @param	inData			リアクション基本データ
 *
 * @return	BOOL			TRUE:メッセージある	FALSE:メッセージない
 */
//------------------------------------------------------------------
static BOOL GetMsgData(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData)
{
	if (inData->Msg){
		//メッセージ用意
		DbgPrint("メッセージあり:%d\n",inData->Msg);
		ptr->Msg = STRBUF_Create( PAIRMSG_TMP_SIZ, HEAPID_WORLD );
		FldTalkBmpAdd( fsys->bgl, &ptr->Win, FLD_MBGFRM_FONT );
		MsgSet( fsys, ptr->Msg, HEAPID_WORLD,inData->Msg-1 );
		{
			const CONFIG * cfg = SaveData_GetConfig( fsys->savedata );
			FieldTalkWinPut( &ptr->Win, cfg );
			ptr->MsgIdx = FieldTalkMsgStart( &ptr->Win, ptr->Msg, cfg, 1 );
			fsys->sublcd_menu_next_flag = 1;		//会話中フラグたてる
		}
		return TRUE;
	}else{
		//メッセージなし
		return FALSE;
	}
}

//------------------------------------------------------------------
/**
 * @brief	アイテム用メッセージセット
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	ptr				リアクション管理ポインタ
 * @param	inMsgType		メッセージの種類識別コード define参照
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetItemGetMsg(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const u8 inMsgType)
{

	ptr->Msg = STRBUF_Create( PAIRMSG_TMP_SIZ, HEAPID_WORLD );
	FldTalkBmpAdd( fsys->bgl, &ptr->Win, FLD_MBGFRM_FONT );
	MsgSet_GetItem( fsys, ptr->Msg, HEAPID_WORLD, inMsgType, ptr->ReactData.Exp.AcceNo);
	{
		const CONFIG * cfg = SaveData_GetConfig( fsys->savedata );
		FieldTalkWinPut( &ptr->Win, cfg );
		ptr->MsgIdx = FieldTalkMsgStart( &ptr->Win, ptr->Msg, cfg, 1 );
		fsys->sublcd_menu_next_flag = 1;		//会話中フラグ立てる
	}
}

//------------------------------------------------------------------
/**
 * @brief	ウェイト取得
 *
 * @param	ptr				リアクション管理ポインタ
 * @param	inData			リアクション基本データ
 *
 * @return	BOOL			TRUE:ウェイトある	FALSE:ウェイトない
 */
//------------------------------------------------------------------
static BOOL GetWait(REACTION_CONT_PTR ptr, const REACT_BASE_DATA * inData)
{
	//ウェイトカウンタクリア
	ptr->Wait = 0;
	if (inData->Wait){
		DbgPrint("ウェイトあり:%d\n",inData->Wait);
		//ウェイトあり
		return TRUE;
	}else{
		//ウェイトなし
		return FALSE;
	}
}

//------------------------------------------------------------------
/**
 * @brief	メッセージセット
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	buf				STRバッファ
 * @param	inHeapID		ヒープID
 * @param	inMsgID			メッセージID
 *
 * @return	none
 */
//------------------------------------------------------------------
static void MsgSet(FIELDSYS_WORK * fsys, STRBUF * buf, const u32 inHeapID, const int inMsgID )
{
	MSGDATA_MANAGER * mman;
	WORDSET * wset;
	STRBUF * str;

	mman = MSGMAN_Create( MSGMAN_TYPE_NORMAL, ARC_MSG, NARC_msg_pair_reaction_dat, inHeapID );
	wset = WORDSET_Create( inHeapID );

	SetMsgTag(fsys, wset);

	str = MSGMAN_AllocString( mman, inMsgID );

	WORDSET_ExpandStr( wset, buf, str );
	STRBUF_Delete( str );
	WORDSET_Delete( wset );
	MSGMAN_Delete( mman );
}

//------------------------------------------------------------------
/**
 * @brief	アイテム用メッセージセット
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	buf				STRバッファ
 * @param	inHeapID		ヒープID
 * @param	inMsgType		メッセージタイプ
 * @param	inAcceNo		アクセサリナンバー
 *
 * @return	none
 */
//------------------------------------------------------------------
static void MsgSet_GetItem(FIELDSYS_WORK * fsys, STRBUF * buf, const u32 inHeapID, const u8 inMsgType, const u8 inAcceNo )
{
	int msg_id;
	MSGDATA_MANAGER * mman;
	WORDSET * wset;
	STRBUF * str;

	mman = MSGMAN_Create( MSGMAN_TYPE_NORMAL, ARC_MSG, NARC_msg_common_scr_dat, inHeapID );
	wset = WORDSET_Create( inHeapID );

	//タグに入る文字列を展開
	if (inMsgType & GET_ACCE){		//アクセサリ取得
		//トレーナー名
		WORDSET_RegisterPlayerName( wset, 0, SaveData_GetMyStatus(fsys->savedata) );
		//アクセサリー名
		WORDSET_RegisterAccessoryName( wset, 1, inAcceNo-1);
		//入手可・不可で分岐
		if (inMsgType & GET_ENABLE){
			msg_id = msg_event_accessory_get_07;
		}else{
			msg_id = msg_event_accessory_get_09;
		}
	}else{		//葉っぱ取得
		POKEMON_PARAM *pp;
		POKEMON_PASO_PARAM * ppp;
		//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
		pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));
		ppp = PPPPointerGet(pp);
		//トレーナー名
		WORDSET_RegisterPlayerName( wset, 0, SaveData_GetMyStatus(fsys->savedata) );
		//ニックネーム
		WORDSET_RegisterPokeNickName( wset, 1, ppp );
		//入手可・不可で分岐
		if (inMsgType & GET_ENABLE){
			msg_id = msg_event_leaf_get_01;
		}else{
			msg_id = msg_event_leaf_get_02;
		}
	}

	str = MSGMAN_AllocString( mman, msg_id );

	WORDSET_ExpandStr( wset, buf, str );
	STRBUF_Delete( str );
	WORDSET_Delete( wset );
	MSGMAN_Delete( mman );

}

//------------------------------------------------------------------
/**
 * @brief	座標セット
 *
 * @param	inData		アクションデータ
 * @param	fldobj		フィールドOBJ
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetXYZ(const ACT_DATA *inData, FIELD_OBJ_PTR fldobj)
{
	VecFx32 vec;
	//座標取得
	FieldOBJ_VecPosGet( fldobj, &vec);
	//データ引継ぎコード以外は現在座標に加算する
	if (inData->Mx){
		vec.x += (inData->Mx*FX32_ONE);
	}
	if (inData->My){
		//ディグダ・ダグトリオはＹオフセットなし
		int monsno = PairPoke_GetMonsNo(fldobj);
		if ((monsno != MONSNO_DHIGUDA)&&(monsno != MONSNO_DAGUTORIO)){
			FieldOBJ_AddPairPokeReactYOfs( fldobj, inData->My );
		}
	}
	if (inData->Mz){
		vec.z += (inData->Mz*FX32_ONE);
	}
	//座標セット
	FieldOBJ_VecPosSet( fldobj, &vec);
}

//------------------------------------------------------------------
/**
 * @brief	SEセット
 *
 * @param	inData			アクションデータ
 * @param	inSE			SE
 * @param	inMonsNo		モンスターナンバー
 * @param	inForm			フォルムナンバー
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetSE(const ACT_DATA *inData, const u16 inSE, const u16 inMonsNo, const u8 inForm)
{
	if (inData->Snd){
		if (!inSE){		//音設定されてない
			return;
		}
		//鳴き声かＳＥかチェック
		if (inSE > SEQ_SE_END){	//鳴き声
			int ptn;
			if (inSE == VOICE_NORMAL){
				ptn = PV_NORMAL;
			}else{
				ptn = PV_PINCHNORMAL;
			}
			Snd_PMVoicePlayEx( ptn, inMonsNo, PV_PTN_PARAM_NONE, PV_PTN_PARAM_NONE, PV_PTN_PARAM_NONE, inForm );
		}else{					//ＳＥ
			Snd_SePlay( inSE );
		}
	}
}

//------------------------------------------------------------------
/**
 * @brief	方向セット
 *
 * @param	ptr			コントローラポインタ
 * @param	inData		アクションデータ
 * @param	fldobj		フィールドOBJ
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetDir(REACTION_CONT_PTR ptr, const ACT_DATA *inData, FIELD_OBJ_PTR fldobj)
{
	//データ引継ぎコード以外は方向をセットする
	if (inData->Dir){
		u8 dir = FieldOBJ_DirDispGet( fldobj );
		FieldOBJ_DirDispSetForce( fldobj, inData->Dir-1 );
		//方向に差分がある場合は草のチェックを行って草追加
		AddGrass(ptr, fldobj, dir);
	}
}

//------------------------------------------------------------------
/**
 * @brief	草追加
 *
 * @param	ptr			コントローラポインタ
 * @param	fldobj		フィールドOBJ
 * @param	inOldDir	旧方向
 *
 * @return	none
 */
//------------------------------------------------------------------
static void AddGrass(REACTION_CONT_PTR ptr, FIELD_OBJ_PTR fldobj, const u8 inOldDir)
{
	u8 now_dir;


	//大きいポケ
	if (!PairPoke_GetInfo_BigSize(fldobj)){
		return;
	}

	now_dir = FieldOBJ_DirDispGet( fldobj );

	//旧方向と現方向が違う
	if (inOldDir == now_dir){
		return;
	}

	//オリジナル方向が、左右
	if ( (ptr->OrgDir != DIR_LEFT)&&(ptr->OrgDir != DIR_RIGHT) ){
		return;
	}

	{
		int x,z;
        u16 attr;
		FIELDSYS_WORK *fsys = FieldOBJ_FieldSysWorkGet( fldobj );
        //検索座標を取得
		GetBackPos(fldobj, ptr->OrgDir, &x, &z);
        attr = GetAttributeLSB( fsys, x, z );
        if( MATR_IsGrass(attr) == TRUE ){
            FE_FldOBJGrass_AddXZ( fldobj, FALSE, x, z, TRUE );
        }else if(  MATR_IsLongGrass(attr) == TRUE ){
			FE_FldOBJLGrass_AddXZ( fldobj, FALSE, x, z, TRUE );
		}
	}
}

//--------------------------------------------------------------
/**
 * 指定方向に対するフィールドＯＢＪの背後の座標を取得する
 *
 * @param	fldobj	フィールドＯＢＪポインタ
 * @param	inDir
 * @param	outX	X座標格納先
 * @param	outZ	Z座標格納先
 *
 * @retval	none
 */
//--------------------------------------------------------------
static void GetBackPos(CONST_FIELD_OBJ_PTR fldobj, const u8 inDir, int *outX, int *outZ)
{
	*outX = FieldOBJ_NowPosGX_Get( fldobj );
	*outZ = FieldOBJ_NowPosGZ_Get( fldobj );
	switch(inDir){
	case DIR_UP:
		(*outZ)++;
		return;
	case DIR_DOWN:
		(*outZ)--;
		return;
	case DIR_LEFT:
		(*outX)++;
		return;
	case DIR_RIGHT:
		(*outX)--;
		return;
	}
	GF_ASSERT(0);
}


//------------------------------------------------------------------
/**
 * @brief	アクション実行
 *
 * @param	ptr				リアクション管理ポインタ
 * @param	fldobj			フィールドOBJ
 *
 * @return	BOOL			TRUE:次のデータへ	FALSE:継続
 */
//------------------------------------------------------------------
static BOOL ExeAction(REACTION_CONT_PTR ptr, FIELD_OBJ_PTR fldobj)
{
	ACT_DATA *act_dat;
	act_dat = &ptr->ActData[ ptr->ActCount ];

	if (ptr->NowFrame == 0){
		//座標をセット
		SetXYZ(act_dat, fldobj);
		//SEとか
		SetSE(act_dat, ptr->ReactData.Base[ ptr->ReactCount ].SE, ptr->MonsNo, ptr->Form);
		//向きセット
		SetDir(ptr, act_dat, fldobj);
	}
	//フレーム加算
	ptr->NowFrame++;

	if (ptr->NowFrame >= act_dat->Frame){
		//次のデータへ
		ptr->ActCount++;
		return TRUE;
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	リアクションデータ取得
 *
 * @param	ptr			リアクション管理ポインタ
 *
 * @return	BOOL	TRUE:データ取得	FALSE:アクション終了
 */
//------------------------------------------------------------------
static BOOL GetData(REACTION_CONT_PTR ptr)
{
	ACT_DATA *act_dat;
	if (ptr->ActCount >= ACT_DATA_MAX){
		DbgPrint("動作数が最大個数を超えた\n");
		return FALSE;
	}

	act_dat = &ptr->ActData[ ptr->ActCount ];
	if (act_dat->Dir == ACT_END){
		return FALSE;
	}else{
		//動作開始
		ptr->NowFrame = 0;
	}
	return TRUE;
}

//------------------------------------------------------------------
/**
 * @brief	アクション関数
 *
 * @param	fsys			フィールドシステムポインタ
 * @param	ptr				リアクション管理ポインタ
 * @param	inActCode		アクションコード
 *
 * @return	BOOL	TRUE:終了	FALSE:継続
 */
//------------------------------------------------------------------
static BOOL Action(FIELDSYS_WORK * fsys, REACTION_CONT_PTR ptr, const int inActCode)
{
	if (!inActCode){
		GF_ASSERT(0);
		return TRUE;
	}

	switch(ptr->Seq){
	case SEQ_LOAD_ACTION:
		ArchiveDataLoad(ptr->ActData, ARC_P_ACT, inActCode-1);
	case SEQ_SAVE_ORG_DIR_POS:		//方向と座標保存
		FieldOBJ_VecPosGet( fsys->PairPokeWork.FldObj, &ptr->OrgPos);
		ptr->OrgDir = FieldOBJ_DirDispGet( fsys->PairPokeWork.FldObj );
		//連れ歩きリアクションＹオフセットクリア
		FieldOBJ_SetPairPokeReactYOfs( fsys->PairPokeWork.FldObj, 0 );
		//向きオフセット無効
		FieldOBJ_PairPokeReactDrawOfsFlg( fsys->PairPokeWork.FldObj, 1 );
		ptr->Seq = SEQ_GET_DATA;
		//カウンタクリア
		ptr->ActCount = 0;
		break;
	case SEQ_GET_DATA:
		if ( !GetData(ptr) ){
			//もうデータない
			ptr->Seq = SEQ_SET_ORG_DIR_POS;
			break;
		}
		ptr->Seq = SEQ_EXE_ACT;
	case SEQ_EXE_ACT:
		if ( ExeAction(ptr, fsys->PairPokeWork.FldObj) ){
			ptr->Seq = SEQ_GET_DATA;
		}
		break;
	case SEQ_SET_ORG_DIR_POS:
		{
			u8 dir = FieldOBJ_DirDispGet( fsys->PairPokeWork.FldObj );
			//連れ歩きリアクションＹオフセットクリア
			FieldOBJ_SetPairPokeReactYOfs( fsys->PairPokeWork.FldObj, 0 );
			//向きオフセット有効
			FieldOBJ_PairPokeReactDrawOfsFlg( fsys->PairPokeWork.FldObj, 0 );
			//方向と座標を戻す
			FieldOBJ_VecPosSet( fsys->PairPokeWork.FldObj, &ptr->OrgPos);
			FieldOBJ_DirDispSetForce( fsys->PairPokeWork.FldObj, ptr->OrgDir );
			//方向に差分がある場合は草のチェックを行って草追加
			AddGrass(ptr, fsys->PairPokeWork.FldObj, dir);
		}
		return TRUE;	//終了
	}

	return  FALSE;		//継続
}

//------------------------------------------------------------------
/**
 * @brief	リアクションイベント
 *
 * @param	event		イベントポインタ
 *
 * @return	BOOL	TRUE:終了		FALSE:継続
 */
//------------------------------------------------------------------
static BOOL GMEVENT_PairReactionStart(GMEVENT_CONTROL * event)
{
	int code;
	int *seq;
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	seq =FieldEvent_GetSeqWork(event);

	switch(*seq){
	case 0:
		code = PairReact_GetReactCode(fsys);
		//コントローラセットアップ
		PairReact_Setup(fsys->ReactCntPtr, code);
		(*seq)++;
		break;
	case 1:
		{
			EXE_REACT_RC rc;
			rc = ExecuteReaction(fsys, fsys->ReactCntPtr);
			if ( rc == EXE_REACT_RC_END ){
				DbgPrint("リアクション終了\n");
				//連れ歩きをポーズ状態にする
				FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
				return TRUE;
			}else if(rc == EXE_REACT_RC_YESNO){
				fsys->ReactCntPtr->ReactSeq = R_SEQ_YES_NO_INIT;
				(*seq) = 2;
			}else if(rc == EXE_REACT_RC_ACCE){
				(*seq) = 3;
			}else if(rc == EXE_REACT_RC_LEAF){
				(*seq) = 4;
			}
		}
		break;
	case 2:
		switch(fsys->ReactCntPtr->ReactSeq){
		case R_SEQ_YES_NO_INIT:
			// 下画面システム切り替え
			FieldSubLcdControler_ChangeApp( fsys, SUBLCD_MODE_YESNO_MENU, NULL );
			fsys->ReactCntPtr->ReactSeq = R_SEQ_YES_NO_MAIN_READY;
			break;
		case R_SEQ_YES_NO_MAIN_READY:
			{
				int app,s_seq;
				app = FieldSubLcdControler_GetNowApp( fsys );
				s_seq = FieldSubLcdControler_GetSequence(fsys);
				// 下画面選択受け入れモードになった事を確認
				if(app==SUBLCD_MODE_YESNO_MENU &&  s_seq==SUBLCD_SEQ_MAIN){
					// はい・いいえ処理に切り替えリクエスト
					FieldSubLcdControler_ChangeSubSeq( fsys, SUBLCD_MODE_YESNO_MENU, 3, &fsys->ReactCntPtr->YesNoAns );
					fsys->ReactCntPtr->ReactSeq = R_SEQ_YES_NO_MAIN;
				}
			}
			break;
		case R_SEQ_YES_NO_MAIN:
			{
				int app,s_seq;
				app = FieldSubLcdControler_GetNowApp( fsys );
				s_seq = FieldSubLcdControler_GetSubSeq( fsys );

				if(app==SUBLCD_MODE_YESNO_MENU &&  s_seq==3+3){
					// 下画面システム切り替え
					FieldSubLcdControler_ChangeApp( fsys, SUBLCD_MODE_FIELD_MENU, NULL );
					fsys->ReactCntPtr->ReactSeq = R_SEQ_YES_NO_END;
				}
			}
			break;
		case R_SEQ_YES_NO_END:
			{
				int app,s_seq;
				app = FieldSubLcdControler_GetNowApp( fsys );
				s_seq = FieldSubLcdControler_GetSequence(fsys);

				// 通常メインメニューに戻った事を確認
				if(app==SUBLCD_MODE_FIELD_MENU &&  s_seq==SUBLCD_SEQ_MAIN){
					switch( fsys->ReactCntPtr->YesNoAns ){
					case 0:		//YES
						//ウィンドウ消す
						{
							BmpTalkWinClear( &fsys->ReactCntPtr->Win, WINDOW_TRANS_ON );
							GF_BGL_BmpWinDel( &fsys->ReactCntPtr->Win );
							STRBUF_Delete( fsys->ReactCntPtr->Msg );
							fsys->sublcd_menu_next_flag = 0;		//会話中フラグ落とす
						}
						//分岐先のリアクションコードを取得
						code = fsys->ReactCntPtr->ReactData.Exp.YesJump;
						if (code == 0){
							//分岐先が無いので、終了
							DbgPrint("YES分岐なし　終了\n");
							//連れ歩きをポーズ状態にする
							FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
							return TRUE;
						}else{
							//コントローラセットアップ
							PairReact_Setup(fsys->ReactCntPtr, code);
							//リアクション実行シーケンス
							(*seq) = 1;
						}
						break;
					case 1:	//NO
						//ウィンドウ消す
						{
							BmpTalkWinClear( &fsys->ReactCntPtr->Win, WINDOW_TRANS_ON );
							GF_BGL_BmpWinDel( &fsys->ReactCntPtr->Win );
							STRBUF_Delete( fsys->ReactCntPtr->Msg );
							fsys->sublcd_menu_next_flag = 0;		//会話中フラグ落とす
						}
						//分岐先のリアクションコードを取得
						code = fsys->ReactCntPtr->ReactData.Exp.NoJump;
						if (code == 0){
							//分岐先が無いので、終了
							DbgPrint("NO分岐なし　終了\n");
							//連れ歩きをポーズ状態にする
							FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
							return TRUE;
						}else{
							//コントローラセットアップ
							PairReact_Setup(fsys->ReactCntPtr, code);
							//リアクション実行シーケンス
							(*seq) = 1;
						}
						break;
					}
				}
			}
			break;
		}
		break;
	case 3:
		{
			BOOL rc;
			int acce_no;
			IMC_SAVEDATA* imc;
			IMC_ITEM_SAVEDATA* imc_item;
			imc	= SaveData_GetImcSaveData(fsys->savedata);
			imc_item = ImcSaveData_GetItemSaveData(imc);	//アイテムセーブデータ取得
			//アクセサリーを入手可能かを調べる
			acce_no = fsys->ReactCntPtr->ReactData.Exp.AcceNo-1;
			GF_ASSERT( (0<=acce_no)&&(acce_no<IMC_ACCE_MAX) );
			rc = ImcSaveData_CheckAcceAdd( imc_item, acce_no, 1 );
			if (rc){		//入手可
				//入手
				ImcSaveData_AddAcceFlag( imc_item, acce_no, 1 );
				//メッセージセット
				SetItemGetMsg(fsys, fsys->ReactCntPtr, GET_ACCE|GET_ENABLE);
				//ME
				Snd_MePlay( SEQ_ME_ACCE );
			}else{		//手持ちいっぱい
				//メッセージセット
				SetItemGetMsg(fsys, fsys->ReactCntPtr, GET_ACCE);
			}
			//メッセージ終了監視シーケンスへ
			(*seq) = 5;
		}
		break;
	case 4:
		{
			POKEMON_PARAM *pp;
			u8 leaf;
			int para_id;
			switch(fsys->ReactCntPtr->ReactData.Exp.LeafNo){
			case 1:
				para_id = ID_PARA_leaf0;
				break;
			case 2:
				para_id = ID_PARA_leaf1;
				break;
			case 3:
				para_id = ID_PARA_leaf2;
				break;
			case 4:
				para_id = ID_PARA_leaf3;
				break;
			case 5:
				para_id = ID_PARA_leaf4;
				break;
			default:
				GF_ASSERT(0);
				return TRUE;
			}
			//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
			pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));
			//葉っぱビットが既に立っているかを調べる
			leaf = PokeParaGet(pp, para_id, NULL);
			if (!leaf){		//未成立　葉っぱ入手可
				u8 buff;
				//葉っぱ入手フラグセット
				{
					EVENTWORK *ev = SaveData_GetEventWork(fsys->savedata);
					SysFlag_SetLeaf( ev );
				}
				//葉っぱ入手
				buff = 1;
				PokeParaPut(pp, para_id, &buff);
				//メッセージセット
				SetItemGetMsg(fsys, fsys->ReactCntPtr, GET_LEAF|GET_ENABLE);
				//ME
				Snd_MePlay( SEQ_ME_ACCE );
			}else{		//成立　葉っぱ入手不可
				//メッセージセット
				SetItemGetMsg(fsys, fsys->ReactCntPtr, GET_LEAF);
			}
			//メッセージ終了監視シーケンスへ
			(*seq) = 5;
		}
		break;
	case 5:
		//メッセージ終了監視
		if( (FldTalkMsgEndCheck( fsys->ReactCntPtr->MsgIdx ) == 1) &&
				(Snd_MePlayCheckBgmPlay() == FALSE) ){
			//キー入力でウィンドウ消す
			if(sys.trg & (PAD_BUTTON_DECIDE|PAD_BUTTON_CANCEL)){
				BmpTalkWinClear( &fsys->ReactCntPtr->Win, WINDOW_TRANS_ON );
				GF_BGL_BmpWinDel( &fsys->ReactCntPtr->Win );
				STRBUF_Delete( fsys->ReactCntPtr->Msg );
				fsys->sublcd_menu_next_flag = 0;		//会話中フラグ落とす
				//終了
				//連れ歩きをポーズ状態にする
				FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
				return TRUE;
			}
		}
		break;
	}

	return FALSE;

}

//------------------------------------------------------------------
/**
 * @brief	メッセージタグセット
 *
 * @param	fsys	フィールドシステムポインタ
 * @param	wset	ワードセットポインタ
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetMsgTag(FIELDSYS_WORK * fsys, WORDSET * wset)
{
	POKEMON_PARAM *pp;
	POKEMON_PASO_PARAM * ppp;
	//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
	pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));
	ppp = PPPPointerGet(pp);

	//ニックネーム
	WORDSET_RegisterPokeNickName( wset, 0, ppp );
	//種族名
	WORDSET_RegisterPokeMonsName( wset, 1, ppp );
	//トレーナー名
	WORDSET_RegisterPlayerName( wset, 2, SaveData_GetMyStatus(fsys->savedata) );
	//地名
	WORDSET_RegisterPokeGetPlace( wset, 3, ZoneData_GetPlaceNameID(fsys->location->zone_id) );
	//持っている道具
	WORDSET_RegisterItemName( wset, 4, PokeParaGet(pp,ID_PARA_item,NULL) );
}

//------------------------------------------------------------------
/**
 * @brief	リアクション後の各値セット
 *
 * @param	fsys		フィールドシステムポインタ
 *
 * @return	none
 */
//------------------------------------------------------------------
static void SetReactAfterVal(FIELDSYS_WORK *fsys)
{
	int val;
	POKEMON_PARAM *pp;
	//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
	pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));

	//機嫌値増減
	val = PAIR_POKE_HUMOR_GetVal(fsys->PairPokeHumor);
	val += fsys->ReactCntPtr->ReactData.Exp.KigenVal;
	if (val > POKE_HUMOR_MAX_VAL){
		val = POKE_HUMOR_MAX_VAL;
	}else if(val < POKE_HUMOR_MIN_VAL){
		val = POKE_HUMOR_MIN_VAL;
	}
	PAIR_POKE_HUMOR_SetVal(fsys->PairPokeHumor, val);

	//なつき度増減
	val = PokeParaGet(pp,ID_PARA_friend,NULL);
	val += fsys->ReactCntPtr->ReactData.Exp.NatsukiVal;
	if (val > 255){
		val = 255;
	}else if(val < 0){
		val = 0;
	}
	PokeParaPut(pp,ID_PARA_friend, &val);
}

//------------------------------------------------------------------
/**
 * @brief	なつき度チェック
 *
 * @param	inNatsukiCode		アーカイバから取得したなつきコード
 * @param	inNatsukiVal		チェックするなつき度
 *
 * @return	BOOL	TRUE:条件満たしてる
 */
//------------------------------------------------------------------
static BOOL CheckNatsuki(const u8 inNatsukiCode, const int inNatsukiVal)
{
	int natsuki = inNatsukiVal;

	switch(inNatsukiCode){
	case MAX:
		if (natsuki == 255){
			return TRUE;
		}
		break;
	case HIGHEST:
		if ( (200<=natsuki)&&(natsuki<255) ){
			return TRUE;
		}
		break;
	case HIGHER:
		if ( (150<=natsuki)&&(natsuki<200) ){
			return TRUE;
		}
		break;
	case HIGH:
		if ( (90<=natsuki)&&(natsuki<150) ){
			return TRUE;
		}
		break;
	case NORMAL:
		if ( (60<=natsuki)&&(natsuki<90) ){
			return TRUE;
		}
		break;
	case LOW:
		if ( (30<=natsuki)&&(natsuki<60) ){
			return TRUE;
		}
		break;
	case LOWER:
		if ( (1<=natsuki)&&(natsuki<30) ){
			return TRUE;
		}
		break;
	case LOWEST:
		if ( natsuki == 0 ){
			return TRUE;
		}
		break;
	case OVER:
		if ( 90<=natsuki ){
			return TRUE;
		}
		break;
	case UNDER:
		if ( natsuki < 60 ){
			return TRUE;
		}
		break;
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	機嫌値チェック
 *
 * @param	inKigenCode		アーカイバから取得した機嫌値コード
 * @param	inKigenVal	チェックする機嫌値コード
 *
 * @return	BOOL	TRUE:条件満たしてる
 */
//------------------------------------------------------------------
static BOOL CheckKigen(const u8 inKigenCode, const int inKigenVal)
{
	int kigen = inKigenVal;

	switch(inKigenCode){
	case MAX:
		if (kigen == POKE_HUMOR_MAX_VAL){
			return TRUE;
		}
		break;
	case HIGHEST:
		if ( (100<=kigen)&&(kigen<POKE_HUMOR_MAX_VAL) ){
			return TRUE;
		}
		break;
	case HIGHER:
		if ( (50<=kigen)&&(kigen<100) ){
			return TRUE;
		}
		break;
	case HIGH:
		if ( (30<=kigen)&&(kigen<50) ){
			return TRUE;
		}
		break;
	case NORMAL:
		if ( (-30<kigen)&&(kigen<30) ){
			return TRUE;
		}
		break;
	case LOW:
		if ( (-50<kigen)&&(kigen<=-30) ){
			return TRUE;
		}
		break;
	case LOWER:
		if ( (POKE_HUMOR_MIN_VAL<kigen)&&(kigen<=-50) ){
			return TRUE;
		}
		break;
	case LOWEST:
		if ( kigen == POKE_HUMOR_MIN_VAL ){
			return TRUE;
		}
		break;
	case OVER:
		if ( 0<=kigen ){
			return TRUE;
		}
		break;
	case UNDER:
		if ( kigen <= -1 ){
			return TRUE;
		}
		break;
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	系統チェック
 *
 * @param	inLineage		アーカイバから取得した系統値
 * @param	inLineageVal	チェックする系統値
 *
 * @return	BOOL	TRUE:条件満たしてる
 */
//------------------------------------------------------------------
static BOOL CheckLineage(const u8 inLineage, const u8 inLineageVal)
{
	if (inLineage <= 249){
		if ( inLineage == inLineageVal ){
			return TRUE;
		}
	}else{
		switch(inLineage){
		case 250:
			if (inLineageVal <= 19){
				return TRUE;
			}
			break;
		case 251:
			if (inLineageVal <= 130){
				return TRUE;
			}
			break;
		case 252:
			if ( (140 <= inLineageVal)&&(inLineageVal <= 149) ){
				return TRUE;
			}
			break;
		case 253:
			if (160 <= inLineageVal){
				return TRUE;
			}
			break;
		case 254:
			if (220 <= inLineageVal){
				return TRUE;
			}
			break;
		default:
			GF_ASSERT(0);
			return FALSE;
		}
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	葉っぱチェック(指定葉っぱナンバーを取得していなければ、条件を満たしている)
 *
 * @param	inLeaf		アーカイバから取得した条件葉っぱナンバー
 * @param	inLeaves	チェックする葉っぱビット群
 *
 * @return	BOOL	TRUE:条件満たしてる
 */
//------------------------------------------------------------------
static BOOL CheckLeaves(const u8 inLeaf, const u8 inLeaves)
{
	int i;
	u8 leaves_mask[LEAVES_MAX] = {
		LEAF00_MASK,
		LEAF01_MASK,
		LEAF02_MASK,
		LEAF03_MASK,
		LEAF04_MASK,
	};
	for (i=0;i<LEAVES_MAX; i++){
		//まだ取得していなければ、条件達成
		if ( !(inLeaves & leaves_mask[inLeaf-1]) ){
			return TRUE;
		}
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	連れ歩きのタイプと指定タイプが同じか？
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	inType		タイプ
 *
 * @return	BOOL	TRUE:タイプ一致		FLASE:タイプ不一致
 */
//------------------------------------------------------------------
BOOL PairReact_IsSameType(FIELDSYS_WORK *fsys, const int inType)
{
	POKEMON_PARAM *pp;
	int type1,type2;
	//連れ歩きポケモンに該当するポケモンパラメータを取得(気絶していない先頭ポケ)
	pp = EvPoke_GetLivingPokemonTop(SaveData_GetTemotiPokemon(fsys->savedata));
	type1 = PokeParaGet(pp,ID_PARA_type1,NULL);
	type2 = PokeParaGet(pp,ID_PARA_type2,NULL);
	if ( (type1 == inType)||(type2 == inType) ){
		return TRUE;
	}
	return FALSE;
}

//------------------------------------------------------------------
/**
 * @brief	連れ歩きのフィールド技使用前ジャンプアクションセット
 *
 * @param	fsys		フィールドシステムポインタ
 * @param	inJumpNum	ジャンプ回数
 *
 * @return	none
 */
//------------------------------------------------------------------
void PairReact_JumpAct(FIELDSYS_WORK *fsys, const u8 inJumpNum)
{
	JUMP_ACT_WORK *work;
	int monsno;

	monsno = PairPoke_GetMonsNo(fsys->PairPokeWork.FldObj);
	//ディグダ・ダグトリオの場合は処理を行わない
	if ((monsno == MONSNO_DHIGUDA)||(monsno == MONSNO_DAGUTORIO)){
		return;
	}

	work = sys_AllocMemoryLo( HEAPID_WORLD, sizeof(JUMP_ACT_WORK) );

	work->CountMax = inJumpNum;
	work->CountNow = 0;

	//イベントを作成
	FieldEvent_Call(fsys->event, GMEVENT_PairPokeJumpAct, work);
}

//------------------------------------------------------------------
/**
 * @brief	連れ歩きのフィールド技使用前ジャンプアクションイベント
 *
 * @param	event		イベントポインタ
 *
 * @return	BOOL	TRUE:イベント終了		FLASE:イベント継続
 */
//------------------------------------------------------------------
static BOOL GMEVENT_PairPokeJumpAct(GMEVENT_CONTROL * event)
{
	int *seq;
	FIELDSYS_WORK * fsys = FieldEvent_GetFieldSysWork(event);
	JUMP_ACT_WORK *work = FieldEvent_GetSpecialWork( event );
	seq = FieldEvent_GetSeqWork(event);

	switch(*seq){
	case 0:	//ポーズを解除
		FieldOBJ_MovePauseClear( fsys->PairPokeWork.FldObj );
		(*seq)++;
		/* FALL THROUGH */
	case 1:
		//アニメ終了待ち後ポーズ
		if ( FieldOBJ_AcmdSetCheck( PairPoke_GetFldObjPtr(fsys) ) ){
			FieldOBJ_MovePause( fsys->PairPokeWork.FldObj );
			(*seq)++;
		}
		break;
	case 2:
		{
			u8 dir;
			//連れ歩きの向き取得
			dir = FieldOBJ_DirDispGet(fsys->PairPokeWork.FldObj);
			OS_Printf("dir%d\n",dir);
			//ジャンプアニメコマンドセット
			work->TcbAcmd = FieldOBJ_AcmdListSet( fsys->PairPokeWork.FldObj, &DATA_JumpAcmdTbl[dir][0] );
		}
		(*seq)++;
		break;
	case 3:
		//アニメ終了待ち
		if ( FieldOBJ_AcmdListEndCheck(work->TcbAcmd) == TRUE ){
			FieldOBJ_AcmdListEnd( work->TcbAcmd );
			//アニメ回数カウントアップ
			work->CountNow++;
			//指定回数アニメをこなしたか？
			if (work->CountNow >= work->CountMax){
				(*seq)++;
			}else{
				(*seq) = 0;
			}
		}
		break;
	case 4:
		//終了
		sys_FreeMemoryEz( work );
		return TRUE;
	}
	return FALSE;
}

#ifdef PM_DEBUG
static void DebugPrintArcData(const REACT_OC_DATA *inData)
{
	DbgPrint("RC:%d\n",inData->RC);
	DbgPrint("Rnd:%d Evt:%d Save:%d Item:%d HP:%d St:%d Obj:%d Hide:%d",
			inData->Rnd, inData->Evt, inData->SaveRC, inData->Item, inData->HP, inData->State, inData->Obj, inData->HideItem);
	DbgPrint("Lv:%d Skill:%d Type:%d Weather:%d Attr:%d Enc:%d Time:%d Kigen:%d",
			inData->EncLv, inData->Skill, inData->Type, inData->Weather, inData->Attr, inData->EncAttr, inData->Time, inData->Kigen);
	DbgPrint("Perform:%d Natsuki:%d Person:%d Lineage:%d Leaf:%d Sex:%d Dir:%d\n",
			inData->Perform, inData->Natsuki, inData->Person, inData->Lineage, inData->Leaf, inData->Sex, inData->Dir);
}

static void DebugPrintfActData(const REACT_BASE_DATA *inData)
{
	DbgPrint("ActCode:%d Msg:%d SE:%d Ballon%d Wait:%d\n",
			inData->ActCode, inData->Msg, inData->SE, inData->Ballon, inData->Wait);
}

void PairReact_SetEvnet(FIELDSYS_WORK * fsys)
{
	//マップジャンプイベントを作成
	FieldEvent_Set(fsys, GMEVENT_PairReactionStart, NULL);
}


#endif